emit -C extra-filename and metadata
authorYehuda Katz + Carl Lerche <engineering@tilde.io>
Tue, 8 Jul 2014 22:50:50 +0000 (15:50 -0700)
committerTim Carey-Smith <tim@spork.in>
Tue, 8 Jul 2014 22:50:50 +0000 (15:50 -0700)
src/cargo/core/manifest.rs
src/cargo/core/package_id.rs
src/cargo/core/source.rs
src/cargo/ops/cargo_rustc.rs
src/cargo/util/hex.rs
src/cargo/util/mod.rs
src/cargo/util/toml.rs

index 048ef6ada28427807ea8047fbb41ae96bbccb2f6..3eee275913f8702f75657b1d361d09be4d0750f0 100644 (file)
@@ -9,6 +9,7 @@ use core::{
     PackageId,
     Summary
 };
+use core::package_id::Metadata;
 use core::dependency::SerializedDependency;
 use util::{CargoResult, human};
 
@@ -99,13 +100,13 @@ pub enum TargetKind {
     BinTarget
 }
 
-#[deriving(Clone, Hash, PartialEq)]
+#[deriving(Encodable, Decodable, Clone, Hash, PartialEq)]
 pub struct Profile {
     env: String, // compile, test, dev, bench, etc.
     opt_level: uint,
     debug: bool,
     test: bool,
-    dest: Option<String>
+    dest: Option<String>,
 }
 
 impl Profile {
@@ -193,15 +194,18 @@ impl Profile {
 pub struct Target {
     kind: TargetKind,
     name: String,
-    path: Path,
-    profile: Profile
+    src_path: Path,
+    profile: Profile,
+    metadata: Option<Metadata>
 }
 
 #[deriving(Encodable)]
 pub struct SerializedTarget {
     kind: Vec<&'static str>,
     name: String,
-    path: String
+    src_path: String,
+    profile: Profile,
+    metadata: Option<Metadata>
 }
 
 impl<E, S: Encoder<E>> Encodable<S, E> for Target {
@@ -214,7 +218,9 @@ impl<E, S: Encoder<E>> Encodable<S, E> for Target {
         SerializedTarget {
             kind: kind,
             name: self.name.clone(),
-            path: self.path.display().to_str()
+            src_path: self.src_path.display().to_str(),
+            profile: self.profile.clone(),
+            metadata: self.metadata.clone()
         }.encode(s)
     }
 }
@@ -222,10 +228,11 @@ impl<E, S: Encoder<E>> Encodable<S, E> for Target {
 impl Show for Target {
     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
         write!(f, "{}(name={}, path={})", self.kind, self.name,
-               self.path.display())
+               self.src_path.display())
     }
 }
 
+
 impl Manifest {
     pub fn new(summary: &Summary, targets: &[Target],
                target_dir: &Path, sources: Vec<SourceId>,
@@ -292,21 +299,26 @@ impl Manifest {
 
 impl Target {
     pub fn lib_target(name: &str, crate_targets: Vec<LibKind>,
-                      path: &Path, profile: &Profile) -> Target {
+                      src_path: &Path, profile: &Profile,
+                      metadata: &Metadata)
+                      -> Target
+    {
         Target {
             kind: LibTarget(crate_targets),
             name: name.to_str(),
-            path: path.clone(),
-            profile: profile.clone()
+            src_path: src_path.clone(),
+            profile: profile.clone(),
+            metadata: Some(metadata.clone())
         }
     }
 
-    pub fn bin_target(name: &str, path: &Path, profile: &Profile) -> Target {
+    pub fn bin_target(name: &str, src_path: &Path, profile: &Profile) -> Target {
         Target {
             kind: BinTarget,
             name: name.to_str(),
-            path: path.clone(),
-            profile: profile.clone()
+            src_path: src_path.clone(),
+            profile: profile.clone(),
+            metadata: None
         }
     }
 
@@ -314,8 +326,8 @@ impl Target {
         self.name.as_slice()
     }
 
-    pub fn get_path<'a>(&'a self) -> &'a Path {
-        &self.path
+    pub fn get_src_path<'a>(&'a self) -> &'a Path {
+        &self.src_path
     }
 
     pub fn is_lib(&self) -> bool {
@@ -336,6 +348,10 @@ impl Target {
         &self.profile
     }
 
+    pub fn get_metadata<'a>(&'a self) -> Option<&'a Metadata> {
+        self.metadata.as_ref()
+    }
+
     pub fn rustc_crate_types(&self) -> Vec<&'static str> {
         match self.kind {
             LibTarget(ref kinds) => {
index 61dfec353b7bd9788117903133fbffd7cc7370ae..03236aa36dd44df418ae7b34d68aa7812464725d 100644 (file)
@@ -9,7 +9,7 @@ use serialize::{
     Decoder
 };
 
-use util::{CargoResult, CargoError};
+use util::{CargoResult, CargoError, short_hash};
 use core::source::SourceId;
 
 trait ToVersion {
@@ -53,7 +53,7 @@ impl<'a> ToUrl for &'a Url {
     }
 }
 
-#[deriving(Clone,PartialEq)]
+#[deriving(Clone, PartialEq)]
 pub struct PackageId {
     name: String,
     version: semver::Version,
@@ -76,6 +76,12 @@ impl CargoError for PackageIdError {
     fn is_human(&self) -> bool { true }
 }
 
+#[deriving(PartialEq, Hash, Clone, Encodable)]
+pub struct Metadata {
+    pub metadata: String,
+    pub extra_filename: String
+}
+
 impl PackageId {
     pub fn new<T: ToVersion>(name: &str, version: T,
                              sid: &SourceId) -> CargoResult<PackageId> {
@@ -98,6 +104,14 @@ impl PackageId {
     pub fn get_source_id<'a>(&'a self) -> &'a SourceId {
         &self.source_id
     }
+
+    pub fn generate_metadata(&self) -> Metadata {
+        let metadata = format!("{}:-:{}:-:{}", self.name, self.version, self.source_id);
+        let extra_filename = short_hash(
+            &(self.name.as_slice(), self.version.to_str(), &self.source_id));
+
+        Metadata { metadata: metadata, extra_filename: extra_filename }
+    }
 }
 
 static central_repo: &'static str = "http://rust-lang.org/central-repo";
index 1046537af073abdd7b4a0ecc23919862877e9f2e..22590a892f9d0f19cb4f08869826cab36d0d0969 100644 (file)
@@ -46,7 +46,7 @@ pub trait Source {
     fn fingerprint(&self, pkg: &Package) -> CargoResult<String>;
 }
 
-#[deriving(Encodable, Decodable, Show, Clone, PartialEq, Eq, PartialOrd, Ord)]
+#[deriving(Encodable, Decodable, Show, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub enum SourceKind {
     /// GitKind(<git reference>) represents a git repository
     GitKind(String),
@@ -56,7 +56,7 @@ pub enum SourceKind {
     RegistryKind
 }
 
-#[deriving(Clone, PartialEq, Eq)]
+#[deriving(Clone, PartialEq, Eq, Hash)]
 pub enum Location {
     Local(Path),
     Remote(Url),
@@ -77,7 +77,7 @@ impl<E, S: Encoder<E>> Encodable<S, E> for Location {
     }
 }
 
-#[deriving(Encodable, Decodable, Clone, Eq)]
+#[deriving(Encodable, Decodable, Clone, Eq, Hash)]
 pub struct SourceId {
     pub kind: SourceKind,
     pub location: Location,
index 57cbdcfedb01b0125ddbb879533e509d32dc04c3..3d3b5660e06137685d14a2cfb1fb9b5fe23679e4 100644 (file)
@@ -121,6 +121,7 @@ fn compile(targets: &[&Target], pkg: &Package,
     // TODO: Figure out how this works with targets
     let fingerprint_loc = cx.dest.join(format!(".{}.fingerprint",
                                                pkg.get_name()));
+
     let (is_fresh, fingerprint) = try!(is_fresh(pkg, &fingerprint_loc, cx,
                                                 targets));
 
@@ -244,10 +245,15 @@ fn prepare_rustc(root: &Path, target: &Target, crate_types: Vec<&str>,
         .env("RUST_LOG", None) // rustc is way too noisy
 }
 
-fn build_base_args(into: &mut Args, target: &Target, crate_types: Vec<&str>,
-                   cx: &Context) {
+fn build_base_args(into: &mut Args,
+                   target: &Target,
+                   crate_types: Vec<&str>,
+                   cx: &Context)
+{
+    let metadata = target.get_metadata();
+
     // TODO: Handle errors in converting paths into args
-    into.push(target.get_path().display().to_str());
+    into.push(target.get_src_path().display().to_str());
 
     into.push("--crate-name".to_str());
     into.push(target.get_name().to_str());
@@ -273,6 +279,17 @@ fn build_base_args(into: &mut Args, target: &Target, crate_types: Vec<&str>,
         into.push("--test".to_str());
     }
 
+    match metadata {
+        Some(m) => {
+            into.push("-C".to_str());
+            into.push(format!("metadata={}", m.metadata));
+
+            into.push("-C".to_str());
+            into.push(format!("extra-filename={}", m.extra_filename));
+        }
+        None => {}
+    }
+
     if target.is_lib() {
         into.push("--out-dir".to_str());
         into.push(out.display().to_str());
index 7512ece21c60abc0355b73a75f37834495aac426..dc1f9d611c2e6d7990e95cfa352053461dd57176 100644 (file)
@@ -1,4 +1,6 @@
 use std::io::MemWriter;
+use std::hash::{Hasher, Hash};
+use std::hash::sip::SipHasher;
 
 use serialize::hex::ToHex;
 
@@ -8,3 +10,7 @@ pub fn to_hex(num: u64) -> String {
     writer.get_ref().to_hex()
 }
 
+pub fn short_hash<H: Hash>(hashable: &H) -> String {
+    let hasher = SipHasher::new_with_keys(0, 0);
+    to_hex(hasher.hash(hashable))
+}
index dfeb92cb081e30bbfacd59d5b0b4fa647450d977..12f86c7d96db131351cdd8c7487691730d296b8d 100644 (file)
@@ -5,7 +5,7 @@ pub use self::errors::{CargoResult, CargoError, BoxError, ChainError, CliResult}
 pub use self::errors::{CliError, FromError, ProcessError};
 pub use self::errors::{process_error, internal_error, internal, human};
 pub use self::paths::realpath;
-pub use self::hex::to_hex;
+pub use self::hex::{to_hex, short_hash};
 pub use self::pool::TaskPool;
 pub use self::dependency_queue::{DependencyQueue, Fresh, Dirty, Freshness};
 
index c42fc5f1c4a50c509baa6523d8ee474581f253a3..d7713194a47a1feae2a6868da00294fa38764569 100644 (file)
@@ -7,6 +7,7 @@ use toml;
 use core::{SourceId, GitKind};
 use core::manifest::{LibKind, Lib, Profile};
 use core::{Summary, Manifest, Target, Dependency, PackageId};
+use core::package_id::Metadata;
 use core::source::Location;
 use util::{CargoResult, Require, human};
 
@@ -236,6 +237,8 @@ impl TomlManifest {
             human("No `package` or `project` section found.")
         }));
 
+        let pkgid = try!(project.to_package_id(source_id));
+        let metadata = pkgid.generate_metadata();
 
         // If we have no lib at all, use the inferred lib if available
         // If we have a lib with a path, we're done
@@ -279,7 +282,8 @@ impl TomlManifest {
 
         // Get targets
         let targets = normalize(lib.as_ref().map(|l| l.as_slice()),
-                                bins.as_ref().map(|b| b.as_slice()));
+                                bins.as_ref().map(|b| b.as_slice()),
+                                &metadata);
 
         if targets.is_empty() {
             debug!("manifest has no build targets; project={}", self.project);
@@ -301,7 +305,6 @@ impl TomlManifest {
             try!(process_dependencies(&mut cx, true, self.dev_dependencies.as_ref()));
         }
 
-        let pkgid = try!(project.to_package_id(source_id));
         let summary = Summary::new(&pkgid, deps.as_slice());
         Ok((Manifest::new(
                 &summary,
@@ -377,7 +380,8 @@ struct TomlTarget {
 }
 
 fn normalize(lib: Option<&[TomlLibTarget]>,
-             bin: Option<&[TomlBinTarget]>)
+             bin: Option<&[TomlBinTarget]>,
+             metadata: &Metadata)
              -> Vec<Target>
 {
     log!(4, "normalizing toml targets; lib={}; bin={}", lib, bin);
@@ -393,7 +397,7 @@ fn normalize(lib: Option<&[TomlLibTarget]>,
         ret
     }
 
-    fn lib_targets(dst: &mut Vec<Target>, libs: &[TomlLibTarget]) {
+    fn lib_targets(dst: &mut Vec<Target>, libs: &[TomlLibTarget], metadata: &Metadata) {
         let l = &libs[0];
         let path = l.path.clone().unwrap_or_else(|| format!("src/{}.rs", l.name));
         let crate_types = l.crate_type.clone().and_then(|kinds| {
@@ -402,7 +406,8 @@ fn normalize(lib: Option<&[TomlLibTarget]>,
 
         for profile in target_profiles(l).iter() {
             dst.push(Target::lib_target(l.name.as_slice(), crate_types.clone(),
-                                        &Path::new(path.as_slice()), profile));
+                                        &Path::new(path.as_slice()), profile,
+                                        metadata));
         }
     }
 
@@ -413,7 +418,8 @@ fn normalize(lib: Option<&[TomlLibTarget]>,
 
             for profile in target_profiles(bin).iter() {
                 dst.push(Target::bin_target(bin.name.as_slice(),
-                                            &Path::new(path.as_slice()), profile));
+                                            &Path::new(path.as_slice()),
+                                            profile));
             }
         }
     }
@@ -422,12 +428,12 @@ fn normalize(lib: Option<&[TomlLibTarget]>,
 
     match (lib, bin) {
         (Some(ref libs), Some(ref bins)) => {
-            lib_targets(&mut ret, libs.as_slice());
+            lib_targets(&mut ret, libs.as_slice(), metadata);
             bin_targets(&mut ret, bins.as_slice(),
                         |bin| format!("src/bin/{}.rs", bin.name));
         },
         (Some(ref libs), None) => {
-            lib_targets(&mut ret, libs.as_slice());
+            lib_targets(&mut ret, libs.as_slice(), metadata);
         },
         (None, Some(ref bins)) => {
             bin_targets(&mut ret, bins.as_slice(),